package com.whu.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;

@Aspect
@Component
public class ApiAspect {

    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 用来记录各个api调用次数
     */
    final Map<String, Integer> executionCountMap = new HashMap<>();
    /**
     * 用来记录各个api发生异常次数
     */
    final Map<String, Integer> exceptionCountMap = new HashMap<>();
    /**
     * 用来记录各个api响应时间
     */
    final Map<String, List<Long>> responseTimeMap = new HashMap<>();

    @Pointcut("execution(* com.whu.service.impl.*.*(..))")
    public void servicePointCut(){
    }

    @Around("servicePointCut()")
    public Object aroundPointCut(ProceedingJoinPoint joinPoint) throws Throwable {

        if(executionCountMap.containsKey(joinPoint.getSignature().toString())){
            executionCountMap.put(joinPoint.getSignature().toString(), executionCountMap.get(joinPoint.getSignature().toString())+1);
        }else{
            executionCountMap.put(joinPoint.getSignature().toString(), 1);
        }

        logger.info("开始执行service的"+joinPoint.getSignature()+"方法");

        long t1 = new Date().getTime();

        Object proceed = null;
        try {
            proceed = joinPoint.proceed();
        } catch (Throwable ex) {
            logger.info(ex.getMessage());
            if(exceptionCountMap.containsKey(joinPoint.getSignature().toString())){
                exceptionCountMap.put(joinPoint.getSignature().toString(), exceptionCountMap.get(joinPoint.getSignature().toString())+1);
            }else{
                exceptionCountMap.put(joinPoint.getSignature().toString(), 1);
            }
        }

        long t2 = new Date().getTime();

        logger.info("service的"+joinPoint.getSignature()+"方法执行结束");
        logger.info("响应时间:"+(t2-t1));

        if(responseTimeMap.containsKey(joinPoint.getSignature().toString())){
            responseTimeMap.get(joinPoint.getSignature().toString()).add(t2 - t1);
        }else{
            List<Long> list = new ArrayList<>();
            list.add(t2-t1);
            responseTimeMap.put(joinPoint.getSignature().toString(), list);
        }

        return proceed;
    }

    @AfterThrowing(pointcut = "servicePointCut()",throwing="ex")
    public void afterThrowingPointCut(JoinPoint jp,Exception ex){

    }

    /**
     * 得到各个api的调用次数
     */
    public void getExecutionCount(){
        for(String key : executionCountMap.keySet()){
            Integer value = executionCountMap.get(key);
            logger.info("service的"+key+"方法共被调用了"+value+"次。");
        }
    }

    /**
     * 得到各个api的异次数
     */
    public void getExceptionCount(){
        for(String key : exceptionCountMap.keySet()){
            Integer value = exceptionCountMap.get(key);
            logger.info("service的"+key+"方法发生了"+value+"次异常。");
        }
    }
    /**
     * 得到各个api的最长响应时间、最短响应时间、平均响应时间
     */
    public void getResponseTime(){
        for (String key : responseTimeMap.keySet()){
            List<Long> value = responseTimeMap.get(key);
            logger.info("service的"+key+"方法的最小响应时间是:"+Collections.min(value).toString());
            logger.info("service的"+key+"方法的最大响应时间是:"+Collections.max(value).toString());
            Long sum = 0L;
            for (Long aLong : value) {
                sum += aLong;
            }
            logger.info("service的"+key+"方法的平均响应时间是:"+String.valueOf(sum/value.size()));
        }
    }

}
